<template>
    <view class="app-upload-file">
        <view v-if="mode == 'image'" class="mode-image">
            <view class="dir-left-wrap list">
                <view class="list-item" v-for="(v, i) in imgList" :key="i" @click="previewImage(i)">
                    <view v-if="!props.readonly" class="main-center cross-center icon-del" @click.stop="delItem(i)">
                        <view class="line"></view>
                        <view class="line rotate"></view>
                    </view>
                    <AppImage :src="v.url" mode="aspectFill"></AppImage>
                    <view v-if="props.progress" class="list-item-progress">
                        <AppProgress :percent="v.progress"></AppProgress>
                    </view>
                </view>
                <view v-if="!props.readonly && (imgList.length < props.limit)"
                    class="main-center cross-center list-item is-icon" @click="selectMedia">
                    <view class="main-center cross-center icon-add">
                        <view class="line"></view>
                        <view class="line rotate"></view>
                    </view>
                </view>
            </view>
        </view>
        <view v-if="mode == 'file'"></view>
        <view v-if="mode == 'video'"></view>
        <view v-if="mode == 'audio'"></view>
    </view>
</template>

<script setup lang='ts' name="AppUploadFile">
import AppImage from "@/components/AppImage/index.vue";
import AppProgress from "@/components/AppProgress/index.vue";
import { config } from "@/config";
import { upload } from "@/lib";
import { ApiCode } from "@/types/api/base";
import { useLogin, usePage } from "@/hooks";
import { api } from "@/api";
import { UploadFile } from "@/types/api/upload";

/**
 * AppUploadFile 上传文件
 * @description 上传文件
 */
export interface AppImageProps {
    /**当前已经上传的列表 */
    modelValue: string[]
    /**当前模式 */
    mode: 'image' | 'file' | 'video' | 'audio'
    /**最大选择个数 ，h5 会自动忽略多选的部分 */
    limit?: number
    /**是否隐藏删除按钮 */
    hideDelIcon?: boolean
    /**禁用预览 */
    disablePreview?: boolean
    /**是否禁用 */
    disabled?: boolean
    /**是否只读 */
    readonly?: boolean
    /**是否显示进度条 */
    progress?: boolean
}
export interface AppImageEmits {
    (e: 'update:modelValue', data: string[]): void
}

const props = withDefaults(defineProps<AppImageProps>(), {
    limit: 6,
    hideDelIcon: false,
    disablePreview: false,
    disabled: false,
    readonly: false,
    progress: false
})
const emit = defineEmits<AppImageEmits>()

/**最多可以选择的文件个数 */
const canSelectCount = computed(() => (props.limit - props.modelValue.length))
const { isLogin } = useLogin()
const { navigate } = usePage()

type Img = {
    url: string,
    progress: number
}
const imgList = ref<Img[]>([])
watch(props.modelValue, (val) => {
    checkImgList()
})
const checkImgList = () => {
    imgList.value = props.modelValue.map(v => ({ url: v, progress: 0 }))
}
onMounted(() => {
    checkImgList()
})


/**删除一条 */
const delItem = (i: number) => {
    imgList.value = imgList.value.filter((item, index) => index !== i)
    updatePropsImgList
}

/**添加一条 */
const addItem = (img: Img) => {
    imgList.value.push(img)
}

/**更新传入的文件列表数组 */
const updatePropsImgList = () => {
    emit('update:modelValue', imgList.value.map(v => v.url))
}

/**更新图片上传进度 */
const updateFileProgress = (task: UniApp.UploadTask, filePath: string) => {
    task.onProgressUpdate((res) => {
        if (imgList.value.findIndex(v => v.url == filePath) == -1) {
            imgList.value.push({
                url: filePath,
                progress: 0,
            })
        } else {
            imgList.value.forEach(v => {
                if (v.url == filePath) {
                    v.progress = res.progress
                }
            })
        }
    })

}

/**选择文件 */
const selectMedia = () => {
    if (!isLogin.value) return navigate(config.loginPage)
    //#ifdef MP
    uni.chooseMedia({
        count: canSelectCount.value,
        mediaType: ['image'],
        success: (e) => {
            const tempFiles = e.tempFiles
            for (let i = 0; i < tempFiles.length; i++) {
                if (i >= (props.limit - imgList.value.length)) {
                    break;
                }
                const curFilePath = tempFiles[i].tempFilePath
                upload<UploadFile>(api.upload.file, {
                    filePath: curFilePath,
                    formData: {
                        filePath: curFilePath,
                        filename: 'file'
                    },
                    callback: (task) => {
                        if (props.progress) {
                            updateFileProgress(task, curFilePath)
                        } else {
                            addItem({
                                url: curFilePath,
                                progress: 0,
                            })
                        }
                    }
                }).then((res) => {
                    if (res.code == ApiCode.success) {
                        imgList.value.forEach(v => {
                            if (v.url == curFilePath) {
                                v.url = res.data.url
                            }
                        })
                        updatePropsImgList()
                    }
                });
            }
        }
    })
    //#endif
    //#ifdef H5
    uni.chooseImage({
        count: canSelectCount.value,
        sizeType: ['original'],
        sourceType: ['album', 'camera'],
        success: (e) => {
            const tempFiles = e.tempFiles as UniApp.ChooseImageSuccessCallbackResultFile[]
            for (let i = 0; i < tempFiles.length; i++) {
                if (i >= (props.limit - imgList.value.length)) {
                    break;
                }
                const curFilePath = tempFiles[i].path
                upload<UploadFile>(api.upload.file, {
                    filePath: curFilePath,
                    formData: {
                        filePath: curFilePath,
                        filename: ''
                    },
                    callback: (task) => {
                        if (props.progress) {
                            updateFileProgress(task, curFilePath)
                        } else {
                            addItem({
                                url: curFilePath,
                                progress: 0,
                            })
                        }
                    }
                }).then((res) => {
                    if (res.code == ApiCode.success) {
                        imgList.value.forEach(v => {
                            if (v.url == curFilePath) {
                                v.url = res.data.url
                            }
                        })
                        updatePropsImgList()
                    }
                });
            }
        }
    });
    //#endif
}

/**预览图片 */
const previewImage = (index: number) => {
    uni.previewImage({
        current: props.modelValue[index],
        urls: props.modelValue
    })
}

</script>

<style scoped lang="scss">
$mode-image-gap: 20rpx;
$radius: 8rpx;

.app-upload-file {
    overflow: hidden;

    .icon-del {
        position: absolute;
        top: 0;
        right: 0;
        width: 60rpx;
        height: 60rpx;
        border-radius: 100%;
        background-color: #333;
        transform: rotate(45deg);
        // #ifdef H5
        z-index: 1;
        // #endif

        .line {
            position: absolute;
            width: 40rpx;
            height: 8rpx;
            background-color: #fff;
            border-radius: $radius;

            &.rotate {
                transform: rotate(90deg);
            }
        }
    }

    .mode-image {
        .list {
            margin-bottom: -$mode-image-gap;

            .list-item {
                position: relative;
                width: 223rpx;
                height: 223rpx;
                margin-right: $mode-image-gap;
                margin-bottom: $mode-image-gap;
                border-radius: $radius;
                overflow: hidden;

                &:nth-child(3n) {
                    margin-right: 0;
                    margin-bottom: 0;
                }

                &.is-icon {
                    background-color: #f8f8f8;
                }

                .icon-add {
                    .line {
                        position: absolute;
                        width: 80rpx;
                        height: 10rpx;
                        background-color: #c8c8c8;
                        border-radius: $radius;

                        &.rotate {
                            transform: rotate(90deg);
                        }
                    }
                }

                .list-item-progress {
                    position: absolute;
                    left: 0;
                    bottom: 0;
                    width: 100%;
                }
            }
        }
    }
}
</style>